import { Request, Response } from 'express';
import { DatabaseConnection } from '@/database/connection';
import { Logger } from '@/utils/logger';
import { 
  ValidationError, 
  NotFoundError,
  asyncHandler 
} from '@/middleware/errorHandler';
import { 
  HealthDataSyncRequest, 
  SleepDataSyncRequest,
  HealthData,
  SleepData
} from '@/types/models';

interface AuthenticatedRequest extends Request {
  user: {
    id: string;
    username: string;
    [key: string]: any;
  };
}

const logger = new Logger('HealthDataController');

export class HealthDataController {
  /**
   * 同步健康数据
   */
  public syncHealthData = asyncHandler(async (req: AuthenticatedRequest, res: Response) => {
    const { user } = req;
    const healthData: HealthDataSyncRequest = req.body;
    const db = DatabaseConnection.getConnection();

    // 数据验证
    if (!healthData.record_date) {
      throw new ValidationError('记录日期是必需的');
    }

    // 计算心率统计
    let avgHeartRate = null;
    let maxHeartRate = null;
    let minHeartRate = null;

    if (healthData.heart_rate_data && healthData.heart_rate_data.length > 0) {
      const validHeartRates = healthData.heart_rate_data.filter(hr => hr > 0);
      if (validHeartRates.length > 0) {
        avgHeartRate = Math.round(validHeartRates.reduce((sum, hr) => sum + hr, 0) / validHeartRates.length);
        maxHeartRate = Math.max(...validHeartRates);
        minHeartRate = Math.min(...validHeartRates);
      }
    }

    const syncData = {
      user_id: user.id,
      record_date: new Date(healthData.record_date),
      steps: healthData.steps || 0,
      distance: healthData.distance || 0,
      calories: healthData.calories || 0,
      active_minutes: healthData.active_minutes || 0,
      heart_rate_data: healthData.heart_rate_data ? JSON.stringify(healthData.heart_rate_data) : null,
      avg_heart_rate: avgHeartRate,
      max_heart_rate: maxHeartRate,
      min_heart_rate: minHeartRate,
      stress_level: healthData.stress_level,
      data_source: healthData.data_source || 'unknown',
      synced_at: new Date(),
      updated_at: new Date()
    };

    try {
      // 使用 INSERT ... ON CONFLICT 或 INSERT ... ON DUPLICATE KEY UPDATE
      await db('health_data')
        .insert(syncData)
        .onConflict(['user_id', 'record_date'])
        .merge([
          'steps', 'distance', 'calories', 'active_minutes',
          'heart_rate_data', 'avg_heart_rate', 'max_heart_rate', 'min_heart_rate',
          'stress_level', 'data_source', 'synced_at', 'updated_at'
        ]);

      logger.info('Health data synced successfully', {
        userId: user.id,
        date: healthData.record_date,
        steps: healthData.steps,
        dataSource: healthData.data_source
      });

      res.json({
        success: true,
        data: {
          syncedAt: new Date().toISOString(),
          recordDate: healthData.record_date
        },
        message: '健康数据同步成功'
      });

    } catch (error) {
      logger.error('Failed to sync health data', { 
        error: error.message, 
        userId: user.id,
        date: healthData.record_date
      });
      throw error;
    }
  });

  /**
   * 同步睡眠数据
   */
  public syncSleepData = asyncHandler(async (req: AuthenticatedRequest, res: Response) => {
    const { user } = req;
    const sleepData: SleepDataSyncRequest = req.body;
    const db = DatabaseConnection.getConnection();

    // 数据验证
    if (!sleepData.sleep_date || !sleepData.bedtime || !sleepData.wake_time) {
      throw new ValidationError('睡眠日期、上床时间和醒来时间是必需的');
    }

    // 计算睡眠效率
    let sleepEfficiency = null;
    if (sleepData.total_duration > 0) {
      const totalTimeInBed = new Date(sleepData.get_up_time).getTime() - new Date(sleepData.bedtime).getTime();
      const totalTimeInBedMinutes = totalTimeInBed / (1000 * 60);
      sleepEfficiency = (sleepData.total_duration / totalTimeInBedMinutes) * 100;
    }

    const syncData = {
      user_id: user.id,
      sleep_date: new Date(sleepData.sleep_date),
      bedtime: new Date(sleepData.bedtime),
      sleep_start: new Date(sleepData.sleep_start),
      wake_time: new Date(sleepData.wake_time),
      get_up_time: new Date(sleepData.get_up_time),
      total_duration: sleepData.total_duration,
      deep_sleep: sleepData.deep_sleep || 0,
      light_sleep: sleepData.light_sleep || 0,
      rem_sleep: sleepData.rem_sleep || 0,
      awake_duration: sleepData.awake_duration || 0,
      sleep_efficiency: sleepEfficiency,
      sleep_score: sleepData.sleep_score,
      wake_up_count: sleepData.wake_up_count || 0,
      sleep_stages: sleepData.sleep_stages ? JSON.stringify(sleepData.sleep_stages) : null,
      data_source: sleepData.data_source || 'unknown',
      synced_at: new Date(),
      updated_at: new Date()
    };

    try {
      await db('sleep_data')
        .insert(syncData)
        .onConflict(['user_id', 'sleep_date'])
        .merge([
          'bedtime', 'sleep_start', 'wake_time', 'get_up_time',
          'total_duration', 'deep_sleep', 'light_sleep', 'rem_sleep',
          'awake_duration', 'sleep_efficiency', 'sleep_score', 'wake_up_count',
          'sleep_stages', 'data_source', 'synced_at', 'updated_at'
        ]);

      logger.info('Sleep data synced successfully', {
        userId: user.id,
        date: sleepData.sleep_date,
        duration: sleepData.total_duration,
        score: sleepData.sleep_score
      });

      res.json({
        success: true,
        data: {
          syncedAt: new Date().toISOString(),
          sleepDate: sleepData.sleep_date
        },
        message: '睡眠数据同步成功'
      });

    } catch (error) {
      logger.error('Failed to sync sleep data', { 
        error: error.message, 
        userId: user.id,
        date: sleepData.sleep_date
      });
      throw error;
    }
  });

  /**
   * 获取最新健康数据
   */
  public getLatestHealthData = asyncHandler(async (req: AuthenticatedRequest, res: Response) => {
    const { user } = req;
    const db = DatabaseConnection.getConnection();

    const latestData = await db('health_data')
      .where('user_id', user.id)
      .orderBy('record_date', 'desc')
      .first();

    if (!latestData) {
      res.json({
        success: true,
        data: this.getDefaultHealthData(user.id),
        message: '暂无健康数据'
      });
      return;
    }

    // 处理心率数据
    let heartRateData = [];
    if (latestData.heart_rate_data) {
      try {
        heartRateData = JSON.parse(latestData.heart_rate_data);
      } catch (error) {
        logger.warn('Failed to parse heart rate data', { userId: user.id });
      }
    }

    const responseData: HealthData = {
      id: latestData.id,
      userId: latestData.user_id,
      date: latestData.record_date,
      steps: latestData.steps,
      distance: latestData.distance,
      calories: latestData.calories,
      activeMinutes: latestData.active_minutes,
      heartRate: heartRateData,
      averageHeartRate: latestData.avg_heart_rate,
      maxHeartRate: latestData.max_heart_rate,
      minHeartRate: latestData.min_heart_rate,
      stressLevel: latestData.stress_level,
      dataSource: latestData.data_source,
      syncedAt: latestData.synced_at,
      createdAt: latestData.created_at,
      updatedAt: latestData.updated_at
    };

    res.json({
      success: true,
      data: responseData
    });
  });

  /**
   * 获取指定日期范围的健康数据
   */
  public getHealthDataByRange = asyncHandler(async (req: AuthenticatedRequest, res: Response) => {
    const { user } = req;
    const { start_date, end_date, limit = 30 } = req.query;
    const db = DatabaseConnection.getConnection();

    if (!start_date || !end_date) {
      throw new ValidationError('开始日期和结束日期是必需的');
    }

    const healthDataList = await db('health_data')
      .where('user_id', user.id)
      .whereBetween('record_date', [start_date as string, end_date as string])
      .orderBy('record_date', 'desc')
      .limit(parseInt(limit as string));

    const responseData = healthDataList.map(data => ({
      id: data.id,
      userId: data.user_id,
      date: data.record_date,
      steps: data.steps,
      distance: data.distance,
      calories: data.calories,
      activeMinutes: data.active_minutes,
      heartRate: data.heart_rate_data ? JSON.parse(data.heart_rate_data) : [],
      averageHeartRate: data.avg_heart_rate,
      maxHeartRate: data.max_heart_rate,
      minHeartRate: data.min_heart_rate,
      stressLevel: data.stress_level,
      dataSource: data.data_source,
      syncedAt: data.synced_at,
      createdAt: data.created_at,
      updatedAt: data.updated_at
    }));

    res.json({
      success: true,
      data: responseData,
      pagination: {
        total: responseData.length,
        limit: parseInt(limit as string)
      }
    });
  });

  /**
   * 获取睡眠数据
   */
  public getSleepData = asyncHandler(async (req: AuthenticatedRequest, res: Response) => {
    const { user } = req;
    const { date } = req.params;
    const db = DatabaseConnection.getConnection();

    if (!date) {
      throw new ValidationError('日期参数是必需的');
    }

    const sleepData = await db('sleep_data')
      .where('user_id', user.id)
      .where('sleep_date', date)
      .first();

    if (!sleepData) {
      throw new NotFoundError('未找到指定日期的睡眠数据');
    }

    // 处理睡眠阶段数据
    let sleepStages = null;
    if (sleepData.sleep_stages) {
      try {
        sleepStages = JSON.parse(sleepData.sleep_stages);
      } catch (error) {
        logger.warn('Failed to parse sleep stages data', { userId: user.id });
      }
    }

    const responseData: SleepData = {
      id: sleepData.id,
      userId: sleepData.user_id,
      sleepDate: sleepData.sleep_date,
      bedtime: sleepData.bedtime,
      sleepStart: sleepData.sleep_start,
      wakeTime: sleepData.wake_time,
      getUpTime: sleepData.get_up_time,
      totalDuration: sleepData.total_duration,
      deepSleep: sleepData.deep_sleep,
      lightSleep: sleepData.light_sleep,
      remSleep: sleepData.rem_sleep,
      awakeDuration: sleepData.awake_duration,
      sleepEfficiency: sleepData.sleep_efficiency,
      sleepScore: sleepData.sleep_score,
      wakeUpCount: sleepData.wake_up_count,
      sleepStages: sleepStages,
      dataSource: sleepData.data_source,
      syncedAt: sleepData.synced_at,
      createdAt: sleepData.created_at,
      updatedAt: sleepData.updated_at
    };

    res.json({
      success: true,
      data: responseData
    });
  });

  /**
   * 获取最近7天的睡眠数据
   */
  public getWeeklySleepData = asyncHandler(async (req: AuthenticatedRequest, res: Response) => {
    const { user } = req;
    const db = DatabaseConnection.getConnection();

    const sevenDaysAgo = new Date();
    sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);

    const sleepDataList = await db('sleep_data')
      .where('user_id', user.id)
      .where('sleep_date', '>=', sevenDaysAgo.toISOString().split('T')[0])
      .orderBy('sleep_date', 'desc')
      .limit(7);

    const responseData = sleepDataList.map(data => ({
      id: data.id,
      userId: data.user_id,
      sleepDate: data.sleep_date,
      bedtime: data.bedtime,
      sleepStart: data.sleep_start,
      wakeTime: data.wake_time,
      getUpTime: data.get_up_time,
      totalDuration: data.total_duration,
      deepSleep: data.deep_sleep,
      lightSleep: data.light_sleep,
      remSleep: data.rem_sleep,
      awakeDuration: data.awake_duration,
      sleepEfficiency: data.sleep_efficiency,
      sleepScore: data.sleep_score,
      wakeUpCount: data.wake_up_count,
      sleepStages: data.sleep_stages ? JSON.parse(data.sleep_stages) : null,
      dataSource: data.data_source,
      syncedAt: data.synced_at,
      createdAt: data.created_at,
      updatedAt: data.updated_at
    }));

    res.json({
      success: true,
      data: responseData
    });
  });

  /**
   * 获取健康趋势数据
   */
  public getHealthTrends = asyncHandler(async (req: AuthenticatedRequest, res: Response) => {
    const { user } = req;
    const { days = 30 } = req.query;
    const db = DatabaseConnection.getConnection();

    const daysCount = parseInt(days as string);
    const startDate = new Date();
    startDate.setDate(startDate.getDate() - daysCount);

    // 获取健康数据
    const healthData = await db('health_data')
      .where('user_id', user.id)
      .where('record_date', '>=', startDate.toISOString().split('T')[0])
      .orderBy('record_date', 'asc');

    // 获取睡眠数据
    const sleepData = await db('sleep_data')
      .where('user_id', user.id)
      .where('sleep_date', '>=', startDate.toISOString().split('T')[0])
      .orderBy('sleep_date', 'asc');

    // 计算趋势
    const trends = {
      steps: this.calculateTrend(healthData.map(d => d.steps)),
      calories: this.calculateTrend(healthData.map(d => d.calories)),
      heartRate: this.calculateTrend(healthData.map(d => d.avg_heart_rate).filter(Boolean)),
      sleep: this.calculateTrend(sleepData.map(d => d.total_duration)),
      sleepScore: this.calculateTrend(sleepData.map(d => d.sleep_score).filter(Boolean))
    };

    res.json({
      success: true,
      data: {
        period: `${daysCount}天`,
        trends,
        healthData: healthData.slice(-7), // 最近7天详细数据
        sleepData: sleepData.slice(-7)
      }
    });
  });

  /**
   * 批量同步健康数据
   */
  public batchSyncHealthData = asyncHandler(async (req: AuthenticatedRequest, res: Response) => {
    const { user } = req;
    const { healthDataList } = req.body;
    const db = DatabaseConnection.getConnection();

    if (!Array.isArray(healthDataList) || healthDataList.length === 0) {
      throw new ValidationError('健康数据列表不能为空');
    }

    const trx = await db.transaction();
    const results = [];

    try {
      for (const healthData of healthDataList) {
        // 计算心率统计
        let avgHeartRate = null;
        let maxHeartRate = null;
        let minHeartRate = null;

        if (healthData.heart_rate_data && healthData.heart_rate_data.length > 0) {
          const validHeartRates = healthData.heart_rate_data.filter(hr => hr > 0);
          if (validHeartRates.length > 0) {
            avgHeartRate = Math.round(validHeartRates.reduce((sum, hr) => sum + hr, 0) / validHeartRates.length);
            maxHeartRate = Math.max(...validHeartRates);
            minHeartRate = Math.min(...validHeartRates);
          }
        }

        const syncData = {
          user_id: user.id,
          record_date: new Date(healthData.record_date),
          steps: healthData.steps || 0,
          distance: healthData.distance || 0,
          calories: healthData.calories || 0,
          active_minutes: healthData.active_minutes || 0,
          heart_rate_data: healthData.heart_rate_data ? JSON.stringify(healthData.heart_rate_data) : null,
          avg_heart_rate: avgHeartRate,
          max_heart_rate: maxHeartRate,
          min_heart_rate: minHeartRate,
          stress_level: healthData.stress_level,
          data_source: healthData.data_source || 'batch_sync',
          synced_at: new Date(),
          updated_at: new Date()
        };

        await trx('health_data')
          .insert(syncData)
          .onConflict(['user_id', 'record_date'])
          .merge([
            'steps', 'distance', 'calories', 'active_minutes',
            'heart_rate_data', 'avg_heart_rate', 'max_heart_rate', 'min_heart_rate',
            'stress_level', 'data_source', 'synced_at', 'updated_at'
          ]);

        results.push({
          date: healthData.record_date,
          success: true
        });
      }

      await trx.commit();

      logger.info('Batch health data sync completed', {
        userId: user.id,
        count: healthDataList.length
      });

      res.json({
        success: true,
        data: {
          processed: healthDataList.length,
          successful: results.length,
          results
        },
        message: '批量健康数据同步成功'
      });

    } catch (error) {
      await trx.rollback();
      logger.error('Batch health data sync failed', {
        error: error.message,
        userId: user.id
      });
      throw error;
    }
  });

  /**
   * 获取默认健康数据
   */
  private getDefaultHealthData(userId: string): HealthData {
    return {
      userId,
      date: new Date().toISOString().split('T')[0],
      steps: 0,
      distance: 0,
      calories: 0,
      activeMinutes: 0,
      heartRate: [],
      averageHeartRate: 0,
      stressLevel: 0,
      dataSource: 'default',
      createdAt: new Date().toISOString(),
      updatedAt: new Date().toISOString()
    };
  }

  /**
   * 计算数据趋势
   */
  private calculateTrend(values: number[]): { trend: string; change: number; average: number } {
    if (values.length < 2) {
      return { trend: 'stable', change: 0, average: values[0] || 0 };
    }

    const average = values.reduce((sum, val) => sum + val, 0) / values.length;
    const firstHalf = values.slice(0, Math.floor(values.length / 2));
    const secondHalf = values.slice(Math.floor(values.length / 2));

    const firstAvg = firstHalf.reduce((sum, val) => sum + val, 0) / firstHalf.length;
    const secondAvg = secondHalf.reduce((sum, val) => sum + val, 0) / secondHalf.length;

    const change = ((secondAvg - firstAvg) / firstAvg) * 100;

    let trend = 'stable';
    if (Math.abs(change) > 5) {
      trend = change > 0 ? 'increasing' : 'decreasing';
    }

    return {
      trend,
      change: Math.round(change * 100) / 100,
      average: Math.round(average * 100) / 100
    };
  }
}